package com.yupi.springbootinit.statemachine.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 通知服务
 * 负责处理系统内的各种通知消息，包括部门通知和里程碑通知
 */
@Slf4j
@Service
public class NotificationService {
    
    /**
     * 通知类型枚举
     */
    public enum NotificationType {
        DEPARTMENT_NOTIFICATION("部门通知"),
        MILESTONE_NOTIFICATION("里程碑通知"),
        TASK_NOTIFICATION("任务通知"),
        SYSTEM_NOTIFICATION("系统通知");
        
        private final String description;
        
        NotificationType(String description) {
            this.description = description;
        }
        
        public String getDescription() { return description; }
    }
    
    /**
     * 通知状态枚举
     */
    public enum NotificationStatus {
        UNREAD("未读"),
        READ("已读"),
        ARCHIVED("已归档");
        
        private final String description;
        
        NotificationStatus(String description) {
            this.description = description;
        }
        
        public String getDescription() { return description; }
    }
    
    /**
     * 通知消息实体
     */
    public static class Notification {
        private Long notificationId;
        private NotificationType type;
        private String title;
        private String content;
        private String targetDepartment;
        private String targetUser;
        private Long businessId; // 关联的业务ID
        private NotificationStatus status;
        private LocalDateTime createTime;
        private LocalDateTime readTime;
        private Integer priority; // 优先级 1-高 2-中 3-低
        
        // 构造函数
        public Notification(NotificationType type, String title, String content) {
            this.type = type;
            this.title = title;
            this.content = content;
            this.status = NotificationStatus.UNREAD;
            this.createTime = LocalDateTime.now();
            this.priority = 2; // 默认中等优先级
        }
        
        // Getters and Setters
        public Long getNotificationId() { return notificationId; }
        public void setNotificationId(Long notificationId) { this.notificationId = notificationId; }
        
        public NotificationType getType() { return type; }
        public void setType(NotificationType type) { this.type = type; }
        
        public String getTitle() { return title; }
        public void setTitle(String title) { this.title = title; }
        
        public String getContent() { return content; }
        public void setContent(String content) { this.content = content; }
        
        public String getTargetDepartment() { return targetDepartment; }
        public void setTargetDepartment(String targetDepartment) { this.targetDepartment = targetDepartment; }
        
        public String getTargetUser() { return targetUser; }
        public void setTargetUser(String targetUser) { this.targetUser = targetUser; }
        
        public Long getBusinessId() { return businessId; }
        public void setBusinessId(Long businessId) { this.businessId = businessId; }
        
        public NotificationStatus getStatus() { return status; }
        public void setStatus(NotificationStatus status) { 
            this.status = status;
            if (status == NotificationStatus.READ && this.readTime == null) {
                this.readTime = LocalDateTime.now();
            }
        }
        
        public LocalDateTime getCreateTime() { return createTime; }
        public LocalDateTime getReadTime() { return readTime; }
        
        public Integer getPriority() { return priority; }
        public void setPriority(Integer priority) { this.priority = priority; }
    }
    
    // 内存存储通知（实际应用中应该使用数据库）
    private final Map<Long, Notification> notificationStorage = new ConcurrentHashMap<>();
    private Long notificationIdCounter = 1L;
    
    /**
     * 通知部门
     */
    public void notifyDepartment(String department, String message) {
        Notification notification = new Notification(
            NotificationType.DEPARTMENT_NOTIFICATION,
            "部门通知",
            message
        );
        notification.setTargetDepartment(department);
        notification.setPriority(1); // 部门通知高优先级
        
        saveNotification(notification);
        
        log.info("发送部门通知: 部门={}, 消息={}", department, message);
    }
    
    /**
     * 通知里程碑事件（通知项目部和管理员）
     */
    public void notifyMilestone(Long orderId, String message) {
        // 通知项目部
        Notification projectNotification = new Notification(
            NotificationType.MILESTONE_NOTIFICATION,
            "订单里程碑",
            message
        );
        projectNotification.setTargetDepartment("项目部");
        projectNotification.setBusinessId(orderId);
        projectNotification.setPriority(1); // 里程碑通知高优先级
        saveNotification(projectNotification);
        
        // 通知管理员
        Notification adminNotification = new Notification(
            NotificationType.MILESTONE_NOTIFICATION,
            "订单里程碑",
            message
        );
        adminNotification.setTargetDepartment("管理员");
        adminNotification.setBusinessId(orderId);
        adminNotification.setPriority(1);
        saveNotification(adminNotification);
        
        log.info("发送里程碑通知: 订单ID={}, 消息={}", orderId, message);
    }
    
    /**
     * 通知特定用户
     */
    public void notifyUser(String userId, String title, String message) {
        Notification notification = new Notification(
            NotificationType.TASK_NOTIFICATION,
            title,
            message
        );
        notification.setTargetUser(userId);
        
        saveNotification(notification);
        
        log.info("发送用户通知: 用户ID={}, 标题={}, 消息={}", userId, title, message);
    }
    
    /**
     * 发送系统通知
     */
    public void notifySystem(String title, String message) {
        Notification notification = new Notification(
            NotificationType.SYSTEM_NOTIFICATION,
            title,
            message
        );
        notification.setPriority(3); // 系统通知低优先级
        
        saveNotification(notification);
        
        log.info("发送系统通知: 标题={}, 消息={}", title, message);
    }
    
    /**
     * 获取部门通知列表
     */
    public List<Notification> getDepartmentNotifications(String department, NotificationStatus status) {
        return notificationStorage.values().stream()
                .filter(notification -> department.equals(notification.getTargetDepartment()))
                .filter(notification -> status == null || status.equals(notification.getStatus()))
                .sorted((n1, n2) -> {
                    // 按优先级和创建时间排序
                    int priorityCompare = n1.getPriority().compareTo(n2.getPriority());
                    if (priorityCompare != 0) {
                        return priorityCompare;
                    }
                    return n2.getCreateTime().compareTo(n1.getCreateTime()); // 最新的在前
                })
                .toList();
    }
    
    /**
     * 获取用户通知列表
     */
    public List<Notification> getUserNotifications(String userId, NotificationStatus status) {
        return notificationStorage.values().stream()
                .filter(notification -> userId.equals(notification.getTargetUser()))
                .filter(notification -> status == null || status.equals(notification.getStatus()))
                .sorted((n1, n2) -> {
                    int priorityCompare = n1.getPriority().compareTo(n2.getPriority());
                    if (priorityCompare != 0) {
                        return priorityCompare;
                    }
                    return n2.getCreateTime().compareTo(n1.getCreateTime());
                })
                .toList();
    }
    
    /**
     * 标记通知为已读
     */
    public boolean markAsRead(Long notificationId) {
        Notification notification = notificationStorage.get(notificationId);
        if (notification != null) {
            notification.setStatus(NotificationStatus.READ);
            log.info("标记通知为已读: 通知ID={}", notificationId);
            return true;
        }
        
        log.warn("通知不存在: 通知ID={}", notificationId);
        return false;
    }
    
    /**
     * 批量标记通知为已读
     */
    public int batchMarkAsRead(List<Long> notificationIds) {
        int markedCount = 0;
        for (Long notificationId : notificationIds) {
            if (markAsRead(notificationId)) {
                markedCount++;
            }
        }
        
        log.info("批量标记通知为已读: 标记数量={}", markedCount);
        return markedCount;
    }
    
    /**
     * 归档通知
     */
    public boolean archiveNotification(Long notificationId) {
        Notification notification = notificationStorage.get(notificationId);
        if (notification != null) {
            notification.setStatus(NotificationStatus.ARCHIVED);
            log.info("归档通知: 通知ID={}", notificationId);
            return true;
        }
        
        return false;
    }
    
    /**
     * 获取通知统计信息
     */
    public Map<String, Object> getNotificationStatistics(String department) {
        List<Notification> departmentNotifications = getDepartmentNotifications(department, null);
        
        long unreadCount = departmentNotifications.stream()
                .filter(notification -> NotificationStatus.UNREAD.equals(notification.getStatus()))
                .count();
        
        long readCount = departmentNotifications.stream()
                .filter(notification -> NotificationStatus.READ.equals(notification.getStatus()))
                .count();
        
        long archivedCount = departmentNotifications.stream()
                .filter(notification -> NotificationStatus.ARCHIVED.equals(notification.getStatus()))
                .count();
        
        Map<String, Object> statistics = new ConcurrentHashMap<>();
        statistics.put("department", department);
        statistics.put("totalNotifications", departmentNotifications.size());
        statistics.put("unreadNotifications", unreadCount);
        statistics.put("readNotifications", readCount);
        statistics.put("archivedNotifications", archivedCount);
        
        return statistics;
    }
    
    /**
     * 清理过期通知
     */
    public int cleanupExpiredNotifications(int daysToKeep) {
        LocalDateTime cutoffTime = LocalDateTime.now().minusDays(daysToKeep);
        
        List<Long> expiredNotificationIds = notificationStorage.values().stream()
                .filter(notification -> notification.getCreateTime().isBefore(cutoffTime))
                .filter(notification -> NotificationStatus.ARCHIVED.equals(notification.getStatus()))
                .map(Notification::getNotificationId)
                .toList();
        
        for (Long notificationId : expiredNotificationIds) {
            notificationStorage.remove(notificationId);
        }
        
        log.info("清理过期通知: 清理数量={}, 保留天数={}", expiredNotificationIds.size(), daysToKeep);
        return expiredNotificationIds.size();
    }
    
    /**
     * 保存通知
     */
    private void saveNotification(Notification notification) {
        notification.setNotificationId(generateNotificationId());
        notificationStorage.put(notification.getNotificationId(), notification);
    }
    
    /**
     * 生成通知ID
     */
    private synchronized Long generateNotificationId() {
        return notificationIdCounter++;
    }
}